import GeneralConfig from '../config/general-config';
import Token from '../models/token';
import CommonService from './common-service';
import LocalStorageService from './local-storage-service';

export default class TokenService {
  private static tokenData: Token | null;

  static get token(): Token {
    if (!this.tokenData) {
      this.loadToken();
    }

    return this.tokenData!;
  }

  /**
   * Check if the access token exists. True means exists. False means does NOT exist.
   */
  static get hasAccessToken(): boolean {
    return !CommonService.isNullOrUndefinedOrEmptyString(this.token.accessToken);
  }

  /**
   * Gets the active refresh token in string.
   */
  static get activeAccessToken(): string {
    return this.token.accessToken;
  }

  /**
   * Check if the refresh token exists. True means exists. False means does NOT exist.
   */
  static get hasRefreshToken(): boolean {
    return !CommonService.isNullOrUndefinedOrEmptyString(this.token.refreshToken);
  }

  /**
   * Gets the current refresh token in string.
   */
  static get activeRefreshToken(): string {
    return this.token.refreshToken;
  }

  /**
 * Gets current token bearer. It might be null.
 */
  static get bearer(): string {
    return this.token.bearer;
  }

  /**
   * Checks if current access token is expired or not.
   * @returns True means access token is expired. False means access token is still active.
   */
  static get isAccessTokenExpired(): boolean {
    // CommonService.getCurrentDate() returns the local time.
    // The object retrieved from storage is UTC format.
    // Use new Date(this.token.localDateExpired) converts the UTC to local time.
    // That's why we need to create a new date instance for comparion.
    return this.token.localDateExpired!.getTime() < CommonService.getCurrentDate().getTime();
  }

  /**
   * Sets the rememberMe property based on user selection.
   * @param rememberMe The boolean value of the user selection.
   */
  static setRememberMe(rememberMe: boolean): void {
    LocalStorageService.saveLocalData(GeneralConfig.localRememberMeStorageKey, rememberMe);
  }

  /**
   * Saves the token based on the data from remote server.
   * @param token The data from remote server. It should contains below properties
   *                  string accessToken
   *                  string refreshToken
   *                  number expiresIn (seconds)
   *                  number requestConsumedSeconds (seconds)
   */
  static saveToken(token: Token): void {
    this.tokenData = token;

    // If users checks 'remember me' the token data will be saved in local storage.
    LocalStorageService.saveLocalData(GeneralConfig.localTokenStorageKey, this.tokenData);
  }

  /**
   * Removes the token from local storage and session storage.
   */
  static removeToken(): void {
    this.tokenData = new Token();

    // Removes the saved token.
    LocalStorageService.removeLocalData(GeneralConfig.localTokenStorageKey);
    // LocalStorageService.removeSessionData(GeneralConfig.localTokenStorageKey);
  }

  /**
   * Tries to load the saved token from local storage or session storage based on remembeMe value.
   */
  private static loadToken(): void {
    let json = LocalStorageService.loadLocalData(GeneralConfig.localTokenStorageKey) as Token;

    // If there is no such value in local storage we will assign a defalut value.
    if (CommonService.isNullOrUndefined(json)) {
      this.tokenData = {} as Token;
    } else {
      this.tokenData = Token.fromJson(json);
    }
  }
}